use swc_common::DUMMY_SP;
use swc_ecma_ast::{
    Accessibility, BinaryOp, BindingIdent, BlockStmt, Class, ClassDecl, ClassMember, ClassMethod,
    Constructor, Decl, ExportDecl, Expr, ExprStmt, Ident, ModuleDecl, ModuleItem, Param, Pat, ReturnStmt,
    Stmt, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsKeywordType, TsKeywordTypeKind,
    TsModuleBlock, TsModuleDecl, TsModuleName, TsNamespaceBody, TsType, TsTypeAnn,
    TsTypeParamInstantiation, VarDecl, VarDeclKind, VarDeclarator,
};
use std::collections::HashMap;
use swc_ecma_utils::quote_ident;
use crate::context::PropPos;
use crate::{context::Context, descriptor, export::ExportedIndex, print::Print, runtime::Runtime};

use self::codec::serialize_field_accessor;

#[derive(Clone)]
pub struct LarkPbRuntime;

impl LarkPbRuntime {
    pub const RUNTIME_PACKAGE: &'static str = "@ohos/protobuf";
    pub const RUNTIME_PACKAGE_NAME: &'static str = "$protobuf";
    pub const LARK_PACKAGE: &'static str = "@ohos/protobuf";
    pub const LARK_PACKAGE_NAME: &'static str = "$lark";

    pub const PB_WRITER_NAME: &'static str = "Writer";
    pub const PB_READER_NAME: &'static str = "Reader";
    
    // Named import constants for @ohos/protobuf
    pub const LARK_DECODER_NAME: &'static str = "Decoder";
    pub const LARK_ENCODER_NAME: &'static str = "Encoder";
    pub const LARK_CREATOR_NAME: &'static str = "Creator";
    pub const LARK_VERIFIER_NAME: &'static str = "Verifier";
    pub const LARK_FROM_OBJECT_NAME: &'static str = "FromObject";
    pub const LARK_TO_OBJECT_NAME: &'static str = "ToObject";
    
    // 注释掉未使用的utils导入
    // pub const PB_UTILS_NAME: &'static str = "utils";

    pub fn new() -> Self {
        Self {}
    }
    
    // Helper method to get named imports from @ohos/protobuf
    pub fn get_lark_import(&self, ctx: &mut Context, import_name: &str) -> Ident {
        ctx.get_import_from(Self::LARK_PACKAGE, import_name)
    }
}

pub mod verify;
pub mod fromObject;
pub mod codec;
pub mod common;
pub mod ctor;
pub mod deserialize;
pub mod serialize;

impl Runtime for LarkPbRuntime {
    fn from_binary(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
    ) -> Vec<Stmt> {
        vec![]
        // self.deserialize_setup_inner(ctx, descriptor)
    }

    fn to_binary(&self, ctx: &mut Context, descriptor: &descriptor::DescriptorProto) -> Vec<Stmt> {
        self.serialize_setup_inner(ctx, descriptor, serialize_field_accessor)
    }

    fn from_json(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
    ) -> Option<ClassMember> {
        None
    }

    fn to_json(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
    ) -> Option<ClassMember> {
        None
    }

    //对应的 TypeScript 类型定义的代码生成器
    fn print_message(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
        ns: &mut Vec<String>,
    ) -> Vec<ModuleItem> {
        if descriptor.options.map_entry() {
            return vec![];
        }
        let ident = quote_ident!(descriptor.name());
        //定义export interface接口
        let interface_decl: ModuleItem = self.print_decl_interface(ctx, descriptor);
        
        // 导入消息中使用的枚举类型
        for field in &descriptor.field {
            if field.is_enum() {
                let enum_type_name = field.type_name().trim_start_matches('.');
                let parts: Vec<&str> = enum_type_name.split('.').collect();
                
                // 获取枚举类型的名称（最后一部分）
                if let Some(enum_name) = parts.last() {
                    // 判断是否是消息内的嵌套枚举
                    let is_part_of_message = parts.len() >= 2 && 
                                            parts[parts.len()-2] != parts[0]; // 如果倒数第二部分不是包名，那就是消息名
                    
                    // 如果不是消息内的嵌套枚举（即顶层枚举或同包下的其他枚举），则需要导入
                    if !is_part_of_message {
                        let _ = ctx.get_import_from(&format!("./{}", enum_name), enum_name);
                    }
                }
            }
        }
        
        let def_decl = self.print_decl_class(ctx, descriptor, ns);
        let mut module_items = vec![];
        ns.push(descriptor.name().to_string());
        //println!("{:?}",module_items);
        if !descriptor.nested_type.is_empty() || !descriptor.enum_type.is_empty() {
            let mut nested_modules = vec![];

            for nested in &descriptor.nested_type {
                nested_modules.extend(self.print_message(ctx, nested, ns));
            }

            for r#enum in &descriptor.enum_type {
                nested_modules.extend(self.print_enum(ctx, r#enum));
            }
            
            module_items.extend(ctx.wrap_if_needed(nested_modules));
        }
        ns.pop();
        module_items.extend(self.print_oneof_decls(ctx, descriptor));

        // 构建最终结果(接口+类+所有嵌套项)
        let mut result = vec![interface_decl, def_decl];
        result.extend(module_items);
        result
        //原来namespace部分代码
        // if module_items.is_empty() {
        //     vec![interface_decl, def_decl]
        // } else {
            // vec![
            //     interface_decl,
            //     def_decl,
            //     ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
            //         span: DUMMY_SP,
            //         decl: Decl::TsModule(Box::new(TsModuleDecl {
            //             span: DUMMY_SP,
            //             declare: false,
            //             global: false,
            //             id: TsModuleName::Ident(ident.clone()),
            //             body: Some(TsNamespaceBody::TsModuleBlock(TsModuleBlock {
            //                 span: DUMMY_SP,
            //                 body: module_items,
            //             })),
            //         })),
            //     })),
            // ]
        // }
    }

    fn print_enum(
        &self,
        _ctx: &mut Context,
        descriptor: &descriptor::EnumDescriptorProto,
    ) -> Vec<ModuleItem> {
        let mut members = vec![];

        for member in descriptor.value.iter() {
            members.push(TsEnumMember {
                span: DUMMY_SP,
                id: TsEnumMemberId::Ident(quote_ident!(member.name())),
                init: Some(Box::new(crate::lit_num!(member.number()).into())),
            })
        }

        let r#enum = Decl::TsEnum(Box::new(TsEnumDecl {
            span: DUMMY_SP,
            declare: false,
            is_const: false,
            id: quote_ident!(descriptor.name()),
            members,
        }));
        vec![ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
            span: DUMMY_SP,
            decl: r#enum,
        }))]
    }

    //消息编解码器的代码生成器
    fn print_codec(
        &self,
        ctx: &mut Context,
        descriptor: &descriptor::DescriptorProto,
        ns: &mut Vec<String>,
    ) -> Vec<ModuleItem> {
       
       //handle import start
        if (!descriptor.nested_type.is_empty() || !descriptor.enum_type.is_empty())
         {
            // Store the namespace string in a local variable first
            let namespace = ctx.get_namespace();
            // Then split it and get the last part
            let message = namespace.split('.').last().unwrap_or("");
            for nested in &descriptor.nested_type { 
                if !nested
                .options.as_ref().and_then(|opt| opt.map_entry)
                .unwrap_or(false) {//过滤掉map类型
                    let _ = ctx.get_import_from(
                        &format!("./{}", descriptor.name()),
                        &format!("I{}", nested.name()),
                    );
                    let _ = ctx.get_import_from(
                        &format!("./{}", descriptor.name()),
                        &format!("{}", nested.name()),
                    );
                }
            }
            // 导入当前消息的嵌套枚举类型
            for r#enum in &descriptor.enum_type {
                let _ = ctx.get_import_from(
                    &format!("./{}", descriptor.name()),
                    &format!("{}", r#enum.name()),
                );
            }
        }

        // 导入消息中使用的枚举类型
        for field in &descriptor.field {
            if field.is_enum() {
                let enum_type_name = field.type_name().trim_start_matches('.');
                let parts: Vec<&str> = enum_type_name.split('.').collect();
                
                // 获取枚举类型的名称（最后一部分）
                if let Some(enum_name) = parts.last() {
                    // 判断是否是消息内的嵌套枚举
                    let is_part_of_message = parts.len() >= 2 && 
                                            parts[parts.len()-2] != parts[0]; // 如果倒数第二部分不是包名，那就是消息名
                    
                    // 如果不是消息内的嵌套枚举（即顶层枚举或同包下的其他枚举），则需要导入
                    if !is_part_of_message {
                        let _ = ctx.get_import_from(&format!("./{}", enum_name), enum_name);
                    }
                }
            }
        }

        let mut oneofs = HashMap::new();
        for member in descriptor.field.clone() {
            if member.has_oneof_index() {
                let _ = oneofs.entry(member.oneof_index()).or_insert_with(|| {
                    let mut fields = descriptor.get_oneof_fields(&member);
                    fields.push(member.clone());
                    fields
                });
            }
        }
        let ctx_ref = &ctx;

        let results: Vec<_> = descriptor
            .oneof_decl
            .iter()
            .enumerate()
            .flat_map(move |(idx, oneof)| {
                oneofs.get(&(idx as _))
                    .unwrap()
                    .iter()
                    .map(move |field| {
                        let class_name = self.oneof_variant_type_name(oneof, field, PropPos::Interface);
                        ctx_ref.get_import_from(
                            &format!("./{}", descriptor.name()),
                            &format!("{}", class_name.as_ref()),
                        );
                       let union_class_name = self.oneof_type_name(oneof, PropPos::Interface);
                       ctx_ref.get_import_from(
                            &format!("./{}", descriptor.name()),
                            &format!("{}", union_class_name.as_ref()),
                        );
                    })
                    .collect::<Vec<_>>()
                    .into_iter()
            })
            .collect();
        //handle import end



        if descriptor.options.map_entry() {
            return vec![];
        }
        let mut codec_items = vec![];
        codec_items.push(self.print_decoder(ctx, descriptor, ns));
        codec_items.push(self.print_encoder(ctx, descriptor, ns));
        codec_items.push(self.print_creator(ctx, descriptor, ns));
        if ctx.options.generate_verify {
            codec_items.push(self.print_verify(ctx, descriptor, ns));
        }
        codec_items.push(self.print_from_object(ctx, descriptor, ns));
        codec_items.push(self.print_to_object(ctx, descriptor, ns));
        ns.push(descriptor.name().to_string());
        for message in &descriptor.nested_type {
            if message.options.map_entry() {
                continue;
            }
            let nested_codec_items = self.print_codec(ctx, message, ns);
            codec_items.push(ModuleItem::ModuleDecl(ModuleDecl::ExportDecl(ExportDecl {
                span: DUMMY_SP,
                decl: Decl::TsModule(Box::new(TsModuleDecl {
                    span: DUMMY_SP,
                    declare: false,
                    global: false,
                    id: TsModuleName::Ident(quote_ident!(format!("${}", message.name()))),
                    body: Some(TsNamespaceBody::TsModuleBlock(TsModuleBlock {
                        span: DUMMY_SP,
                        body: nested_codec_items,
                    })),
                })),
            })));
        }
        ns.pop();

        codec_items
    }

    fn print_index(&self, ctx: &mut Context, index: &ExportedIndex) -> Vec<ModuleItem> {
        let mut items = index.print();

        ctx.drain_imports().into_iter().chain(items).collect()
    }
}
